﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using McTools.Xrm.Connection;
using McTools.Xrm.Connection.WinForms;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Messages;

namespace ImportGUI
{
    public partial class Form1 : Form
    {
        #region Variables

        /// <summary>
        /// Dynamics CRM 2011 organization service
        /// </summary>
        IOrganizationService service;

        /// <summary>
        /// Connection control
        /// </summary>
        CrmConnectionStatusBar ccsb;

        /// <summary>
        /// Connection manager
        /// </summary>
        ConnectionManager cManager;

        private FormHelper formHelper;

        #endregion Variables

        public Form1()
        {
            InitializeComponent();

            // Create the connection manager with its events
            this.cManager = new ConnectionManager();
            this.cManager.ConnectionSucceed += new ConnectionManager.ConnectionSucceedEventHandler(cManager_ConnectionSucceed);
            this.cManager.ConnectionFailed += new ConnectionManager.ConnectionFailedEventHandler(cManager_ConnectionFailed);
            this.cManager.StepChanged += new ConnectionManager.StepChangedEventHandler(cManager_StepChanged);
            this.cManager.RequestPassword += new ConnectionManager.RequestPasswordEventHandler(cManager_RequestPassword);
            this.cManager.UseProxy += new ConnectionManager.UseProxyEventHandler(cManager_UseProxy);
            formHelper = new FormHelper(this, cManager);

            // Instantiate and add the connection control to the form
            ccsb = new CrmConnectionStatusBar(this.cManager, formHelper);
            this.Controls.Add(ccsb);
        }

        void cManager_UseProxy(object sender, UseProxyEventArgs e)
        {
            formHelper.SelectProxy();
        }

        bool cManager_RequestPassword(object sender, RequestPasswordEventArgs e)
        {
            return formHelper.RequestPassword(e.ConnectionDetail);
        }

        /// <summary>
        /// Occurs when the connection manager sends a step change
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void cManager_StepChanged(object sender, StepChangedEventArgs e)
        {
            this.ccsb.SetMessage(e.CurrentStep);
        }

        /// <summary>
        /// Occurs when the connection to a server failed
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void cManager_ConnectionFailed(object sender, ConnectionFailedEventArgs e)
        {
            // Set error message
            this.ccsb.SetMessage("Error: " + e.FailureReason);

            // Clear the current organization service
            this.service = null;
        }

        /// <summary>
        /// Occurs when the connection to a server succeed
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        void cManager_ConnectionSucceed(object sender, ConnectionSucceedEventArgs e)
        {
            ccsb.RebuildConnectionList();

            // Store connection Organization Service
            this.service = e.OrganizationService;

            // Displays connection status
            this.ccsb.SetConnectionStatus(true, e.ConnectionDetail);

            // Clear the current action message
            this.ccsb.SetMessage(string.Empty);

            listEntities();
        }

        private void listEntities()
        {
            RetrieveAllEntitiesRequest req = new RetrieveAllEntitiesRequest();
            req.EntityFilters = Microsoft.Xrm.Sdk.Metadata.EntityFilters.Entity;
            req.RetrieveAsIfPublished = true;

            RetrieveAllEntitiesResponse resp = (RetrieveAllEntitiesResponse)service.Execute(req);

            entitiesComboBox.Items.Clear();
            entitiesComboBox.DisplayMember = "Text";
            entitiesComboBox.ValueMember = "Value";

            List<ComboBoxItem> entities = new List<ComboBoxItem>();

            foreach (var item in resp.EntityMetadata)
            {
                if (item.IsCustomizable.Value)
                {
                    entities.Add(new ComboBoxItem((item.DisplayName.UserLocalizedLabel != null ? item.DisplayName.UserLocalizedLabel.Label : item.LogicalName), item.LogicalName));
                }
            }

            entitiesComboBox.Items.AddRange(entities.OrderBy(e=>e.Text).ToArray());
        }

        private void chooseFileButton_Click(object sender, EventArgs e)
        {
            var result = openFileDialog1.ShowDialog();
            if (result == System.Windows.Forms.DialogResult.OK)
            {
                csvFileTextBox.Text = openFileDialog1.FileName;
            }
        }

        private void addToLog(string message)
        {
            logTextBox.AppendText(message);
            logTextBox.AppendText(Environment.NewLine);
        }

        private void importButton_Click(object sender, EventArgs e)
        {
            if (string.IsNullOrEmpty(csvFileTextBox.Text) || entitiesComboBox.SelectedItem == null)
            {
                MessageBox.Show("Please select both an import file and entity before continuing");
                return;
            }
            logTextBox.Clear();
            addToLog(string.Format("Importing file: {0}", csvFileTextBox.Text));
            addToLog(string.Format("    into entity: {0}", ((ComboBoxItem)entitiesComboBox.SelectedItem).Text));

            MSCRM.DataLoad.DataLoad dataloader = new MSCRM.DataLoad.DataLoad(new Microsoft.Xrm.Client.CrmOrganizationServiceContext(service));
            dataloader.LogEvent += dataloader_LogEvent;

            dataloader.Import(csvFileTextBox.Text, ((ComboBoxItem)entitiesComboBox.SelectedItem).Value, ",");

            dataloader.LogEvent -= dataloader_LogEvent;
        }

        void dataloader_LogEvent(object sender, MSCRM.DataLoad.LogEventArgs e)
        {
            addToLog(string.Format("{0}", e.LogMessage));
        }
    }

    public class ComboBoxItem
    {
        public ComboBoxItem(string text, string value)
        {
            this.Text = text;
            this.Value = value;
        }

        public string Text { get; set; }
        public string Value { get; set; }
    }
}
